﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Services;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
using CommonSearchModule;
using System.Runtime.Serialization.Formatters.Binary;
using System.Configuration;
using Lucene.Net.Search;
using Lucene.Net.Index;
using Lucene.Net.Analysis.Standard;
using LuceneIO = Lucene.Net.Store;
using Lucene.Net.Documents;
using Lucene.Net.QueryParsers;
namespace ReadFile.WebService
{
    /// <summary>
    /// ReadFile 的摘要说明
    /// </summary>
    [WebService(Namespace = "http://tempuri.org/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    [System.ComponentModel.ToolboxItem(false)]
    // 若要允许使用 ASP.NET AJAX 从脚本中调用此 Web 服务，请取消对下行的注释。
    // [System.Web.Script.Services.ScriptService]
    public class ReadFileIndex : System.Web.Services.WebService
    {

        StandardAnalyzer standardAnalyzer = new StandardAnalyzer(Lucene.Net.Util.Version.LUCENE_29);
        /// <summary>
        /// 版本：1.0
        /// 根据条件获取指定的索引
        /// WS方法参数不能用int?（Nullable<int> ）这种结构体类型
        /// </summary>
        /// <param name="module">指定索引文件的路径</param>
        /// <param name="keyword"></param>
        /// <param name="categoryName"></param>
        /// <param name="propertyName"></param>
        /// <param name="page"></param>
        /// <param name="pagesize"></param>
        /// <returns></returns>
        [WebMethod]
        public byte[] ReadLocalFile(string module, string keyword, string categoryName, string propertyName, int page, int pagesize)
        {
            return ReadLocalFile1_1(module, keyword, categoryName, propertyName, page, pagesize, string.Empty, string.Empty, string.Empty, string.Empty);
        }
        /// <summary>
        /// 版本：1.1
        /// 根据条件获取指定的索引
        /// WS方法参数不能用int?（Nullable<int> ）这种结构体类型</summary>
        /// <param name="module"></param>
        /// <param name="keyword"></param>
        /// <param name="categoryName"></param>
        /// <param name="propertyName"></param>
        /// <param name="page"></param>
        /// <param name="pagesize"></param>
        /// <param name="minPrice"></param>
        /// <param name="maxPrice"></param>
        /// <param name="sortBy"></param>
        /// <param name="searchUrlType"></param>
        /// <returns></returns>
        [WebMethod]
        public byte[] ReadLocalFile1_1(string module, string keyword, string categoryName, string propertyName, int page, int pagesize, string minPrice, string maxPrice, string sortBy, string searchUrlType)
        {
            string _keyword = (keyword ?? string.Empty).Trim();
            string _categoryName = (categoryName ?? string.Empty).Trim();
            string _propertyName = propertyName;
            int _sortBy = 0;
            int.TryParse(sortBy, out _sortBy);

            SearchResult result = GetDataFromIndex(module, new QueryTerm
            {
                KeyWord = _keyword,
                CategoryName = _categoryName,
                PropertyName = _propertyName,
                PageSize = pagesize,
                PageIndex = page,
                MinPrice = minPrice,
                MaxPrice = maxPrice,
                SortBy = _sortBy,
                SearchUrlType = searchUrlType,
            });
            return result.Serialization();
        }

        [WebMethod]
        public string ReadLocalFileForXML(string module, string keyword, string categoryName, string propertyName, int page, int pagesize, string minPrice, string maxPrice, string sortBy, string searchUrlType)
        {
            string _keyword = (keyword ?? string.Empty).Trim();
            string _categoryName = (categoryName ?? string.Empty).Trim();
            string _propertyName = propertyName;
            int _sortBy = 0;
            int.TryParse(sortBy, out _sortBy);
            SearchResult result = GetDataFromIndex(module, new QueryTerm
             {
                 KeyWord = _keyword,
                 CategoryName = _categoryName,
                 PropertyName = _propertyName,
                 PageSize = pagesize,
                 PageIndex = page,
                 MinPrice = minPrice,
                 MaxPrice = maxPrice,
                 SortBy = _sortBy,
                 SearchUrlType = searchUrlType,

             });
            return result.Serialization(SerializationType.XML);
        }
        DirectoryInfo dirInfo = null;
        LuceneIO.Directory directory = null;

        /// <summary>
        /// 更新索引的document
        /// </summary>
        /// <param name="primarKey">由实体名称+主键组成</param>
        /// <param name="name"></param>
        /// <param name="info"></param>
        /// <param name="categoryName"></param>
        /// <param name="propertyName"></param>
        /// <param name="passKey"></param>
        /// <returns>１表示成功，０表示失败</returns>
        [WebMethod]
        public int UpdateLuceneDocument(string primaryKey, string id, string name, string info, string categoryName, string propertyName, string module, string passKey)
        {
            return UpdateLuceneDocument1_1(primaryKey, id, name, info, categoryName, propertyName, null, null, module, passKey);
        }
        /// <summary>
        /// 版本：1.1 
        /// 更新索引的document
        /// </summary>
        /// <param name="primarKey">由实体名称+主键组成</param>
        /// <param name="name"></param>
        /// <param name="info"></param>
        /// <param name="categoryName"></param>
        /// <param name="propertyName"></param>
        /// <param name="passKey"></param>
        /// <returns>１表示成功，０表示失败</returns>
        [WebMethod]
        public int UpdateLuceneDocument1_1(string primaryKey, string id, string name, string info, string categoryName, string propertyName, string price, string packageTime, string module, string passKey)
        {
            int flag = 0;
            try
            {
                dirInfo = Directory.CreateDirectory(this.GetIndexPath(ConfigurationManager.AppSettings[module]));
                directory = LuceneIO.FSDirectory.Open(dirInfo);
                if (IndexWriter.IsLocked(directory))
                    IndexWriter.Unlock(directory);

                QueryParser parser = new QueryParser(Lucene.Net.Util.Version.LUCENE_29, "PrimaryKey", new StandardAnalyzer(Lucene.Net.Util.Version.LUCENE_29));
                Query query = parser.Parse(primaryKey);
                IndexSearcher indexSearcher = new IndexSearcher(directory);
                Hits hits = indexSearcher.Search(query);
                if (hits.Length() > 0)
                {
                    Document doc = hits.Doc(0);
                    IndexWriter writer = new IndexWriter(directory, new StandardAnalyzer(Lucene.Net.Util.Version.LUCENE_29), false, IndexWriter.MaxFieldLength.UNLIMITED);


                    double _price;
                    double.TryParse(price, out _price);
                    if (!string.IsNullOrEmpty(name))
                    {
                        doc.RemoveField(FieldKeys.Name);
                        doc.Add(new Field(FieldKeys.Name, name, Field.Store.YES, Field.Index.ANALYZED));
                    }
                    if (!string.IsNullOrEmpty(info))
                    {
                        doc.RemoveField(FieldKeys.Info);
                        doc.Add(new Field(FieldKeys.Info, info, Field.Store.YES, Field.Index.ANALYZED));
                    }
                    if (!string.IsNullOrEmpty(categoryName))
                    {
                        doc.RemoveField(FieldKeys.CategoryName);
                        doc.Add(new Field(FieldKeys.CategoryName, categoryName, Field.Store.YES, Field.Index.ANALYZED));
                    }
                    if (!string.IsNullOrEmpty(propertyName))
                    {
                        doc.RemoveField(FieldKeys.PropertyName);
                        doc.Add(new Field(FieldKeys.PropertyName, propertyName, Field.Store.YES, Field.Index.ANALYZED));
                    }
                    if (!string.IsNullOrEmpty(price))
                    {
                        doc.RemoveField(FieldKeys.Price);
                        doc.Add(new NumericField(FieldKeys.Price, Field.Store.YES, true).SetDoubleValue(_price));//double类型
                    }
                    if (!string.IsNullOrEmpty(packageTime))
                    {
                        doc.RemoveField(FieldKeys.PackageTime);
                        doc.Add(new Field(FieldKeys.PackageTime, packageTime, Field.Store.YES, Field.Index.ANALYZED));
                    }




                    writer.DeleteDocuments(query);
                    writer.Optimize();
                    writer.Close();
                    writer = new IndexWriter(directory, new StandardAnalyzer(Lucene.Net.Util.Version.LUCENE_29), false, IndexWriter.MaxFieldLength.UNLIMITED);
                    writer.AddDocument(doc);
                    writer.Optimize();
                    writer.Close();
                }

                flag = 1;
            }
            catch (Exception)
            {

                throw;
            }

            return flag;
        }

        /// <summary>
        /// 删除指定documentId的索引记录
        /// </summary>
        /// <param name="primarKey">由实体名称+主键组成</param>
        /// <param name="passKey"></param>
        /// <returns></returns>
        [WebMethod]
        public int DeleteLuceneDocument(string primaryKey, string module, string passKey)
        {
            int flag = 0;
            try
            {
                dirInfo = Directory.CreateDirectory(this.GetIndexPath(ConfigurationManager.AppSettings[module]));
                directory = LuceneIO.FSDirectory.Open(dirInfo);
                if (IndexWriter.IsLocked(directory))
                    IndexWriter.Unlock(directory);
                IndexWriter writer = new IndexWriter(directory, standardAnalyzer, false, IndexWriter.MaxFieldLength.UNLIMITED);
                QueryParser parser = new QueryParser(Lucene.Net.Util.Version.LUCENE_29, "PrimaryKey", new StandardAnalyzer(Lucene.Net.Util.Version.LUCENE_29));
                Query query = parser.Parse(primaryKey);
                writer.DeleteDocuments(query);
                writer.Commit();
                writer.Optimize();
                writer.Close();
                flag = 1;
            }
            catch (Exception)
            {

                throw;
            }
            return flag;
        }
        /// <summary>
        /// 向索引document中追加记录
        /// </summary>
        /// <param name="primarKey">由实体名称+主键组成</param>
        /// <param name="name"></param>
        /// <param name="info"></param>
        /// <param name="categoryName"></param>
        /// <param name="propertyName"></param>
        /// <param name="passKey"></param>
        /// <returns></returns>
        [WebMethod]
        public int AppendLuceneDocument(string primaryKey, string id, string name, string info, string categoryName, string propertyName, string module, string passKey)
        {
            return AppendLuceneDocument1_1(primaryKey, id, name, info, categoryName, propertyName, null, null, module, passKey, null, null, null);
        }

        /// <summary>
        /// 版本1.1
        /// 向索引document中追加记录
        /// </summary>
        /// <param name="primarKey">由实体名称+主键组成</param>
        /// <param name="name"></param>
        /// <param name="info"></param>
        /// <param name="categoryName"></param>
        /// <param name="propertyName"></param>
        /// <param name="passKey"></param>
        /// <returns></returns>
        [WebMethod]
        public int AppendLuceneDocument1_1(string primaryKey, string id, string name, string info, string categoryName, string propertyName, string price, string packageTime, string module, string passKey, string searchUrlType, string classHour, string picture)
        {
            int flag = 0;
            try
            {
                double _price;
                double.TryParse(price, out _price);
                dirInfo = Directory.CreateDirectory(this.GetIndexPath(ConfigurationManager.AppSettings[module]));
                directory = LuceneIO.FSDirectory.Open(dirInfo);
                if (IndexWriter.IsLocked(directory))
                    IndexWriter.Unlock(directory);
                IndexWriter writer = new IndexWriter(directory, new StandardAnalyzer(Lucene.Net.Util.Version.LUCENE_29), false, IndexWriter.MaxFieldLength.UNLIMITED);
                Document doc = new Document();
                doc.Add(new Field(FieldKeys.PrimaryKey, primaryKey, Field.Store.YES, Field.Index.ANALYZED));
                doc.Add(new Field(FieldKeys.ID, id, Field.Store.YES, Field.Index.ANALYZED));
                if (!string.IsNullOrEmpty(name))
                    doc.Add(new Field(FieldKeys.Name, name, Field.Store.YES, Field.Index.ANALYZED));
                if (!string.IsNullOrEmpty(info))
                    doc.Add(new Field(FieldKeys.Info, info, Field.Store.YES, Field.Index.ANALYZED));
                if (!string.IsNullOrEmpty(categoryName))
                    doc.Add(new Field(FieldKeys.CategoryName, categoryName, Field.Store.YES, Field.Index.ANALYZED));
                if (!string.IsNullOrEmpty(propertyName))
                    doc.Add(new Field(FieldKeys.PropertyName, propertyName, Field.Store.YES, Field.Index.ANALYZED));
                if (!string.IsNullOrEmpty(price))
                    doc.Add(new NumericField(FieldKeys.Price, Field.Store.YES, true).SetDoubleValue(_price));//double类型
                if (!string.IsNullOrEmpty(packageTime))
                    doc.Add(new Field(FieldKeys.PackageTime, packageTime, Field.Store.YES, Field.Index.ANALYZED));

                doc.Add(new Field(FieldKeys.SearchUrlType, string.IsNullOrEmpty(searchUrlType) ? "1" : searchUrlType, Field.Store.YES, Field.Index.ANALYZED));
                doc.Add(new Field(FieldKeys.ExtentionField1, string.IsNullOrEmpty(classHour) ? "0" : classHour, Field.Store.YES, Field.Index.ANALYZED));
                doc.Add(new Field(FieldKeys.ExtentionField3, string.IsNullOrEmpty(picture) ? string.Empty : picture, Field.Store.YES, Field.Index.ANALYZED));


                writer.AddDocument(doc);
                writer.Optimize();
                writer.Close();
                flag = 1;
            }
            catch (Exception)
            {

                throw;
            }
            return flag;
        }

        #region 获取索引
        /// <summary>
        /// 从索引文件中重到数据，根据关键字
        /// </summary>
        /// <param name="keyword"></param>
        /// <returns></returns>
        protected virtual SearchResult GetDataFromIndex(string module, QueryTerm queryTerm)
        {
            if (ConfigurationManager.AppSettings[module] == null)
                throw new Exception("你的" + module + "不能被服务识别");
            QueryTerm term = queryTerm;
            Search searcher = new Search(this.GetIndexPath(ConfigurationManager.AppSettings[module]), term);
            return searcher.GetSearchResult();
        }

        /// <summary>
        /// 调用WIN API方法
        /// 非托管资源
        /// </summary>
        /// <param name="section"></param>
        /// <param name="key"></param>
        /// <param name="def"></param>
        /// <param name="retVal"></param>
        /// <param name="size"></param>
        /// <param name="filePath"></param>
        /// <returns></returns>
        [DllImport("kernel32")]
        private static extern int GetPrivateProfileString(string section, string key, string def, StringBuilder retVal, int size, string filePath);

        /// <summary>
        /// 得到索引文件路径
        /// </summary>
        /// <param name="configPath"></param>
        /// <returns></returns>
        protected string GetIndexPath(string configPath)
        {
            StringBuilder sbPath = new StringBuilder(500);
            GetPrivateProfileString("Index", "Path", "", sbPath, 500, configPath);

            return sbPath.ToString();
        }
        #endregion

    }
}
